/*
 * @Author 舜君
 * @Date 2021-07-31 01:38:34
 * @LastEditTime 2021-07-31 22:59:58
 * @LastEditors 舜君
 * @Description
 * @FilePath /BFFNodeServer/utils/myUnderScore.js
 */

(function () {
  "use strict";

  // 判断执行环境
  var root =
    globalThis ||
    (typeof self === "object" && self.self === self && self) ||
    (typeof global === "object" && global.global === global && global) ||
    this ||
    {};

  var ArrayProto = Array.prototype;

  // 创建一个全局的安全引用
  var _ = function (obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapper = obj;
  };

  _.each = function (obj, fn) {
    if (Array.isArray(obj)) {
      for (var i = 0; i < obj.length; i++) {
        fn(obj[i]);
      }
    }
  };

  _.isfunction = function (obj) {
    return typeof obj === "function";
  };

  _.functions = function (obj) {
    const names = [];
    for (const name in obj) {
      if (_.isfunction(obj[name])) {
        names.push(name);
      }
    }
    return names;
  };

  _.chain = function (obj) {
    const instance = _(obj);
    instance._chain = true;
    return instance;
  };

  function chainResult(instance, obj) {
    return instance._chain ? _.chain(obj) : obj;
  }

  _.mixin = function (obj) {
    _.each(_.functions(obj), (name) => {
      const func = (_[name] = obj[name]);
      _.prototype[name] = function () {
        const args = [this._wrapper];
        args.push(...arguments);
        return chainResult(this, func.apply(_, args));
      };
    });
  };

  _.mixin(_);

  _.each(["forEach"], (name) => {
    const method = ArrayProto[name];
    _.prototype[name] = function (...args) {
      const obj = this._wrapper;
      method.call(obj, ...args);
      if (name === "shift" || (name === "splice" && obj.length === 0))
        delete obj[0];
      return chainResult(this, obj);
    };
  });

  root._ = _;
})();

_([1, 2, 3]).each((val) => {
  console.log(val);
});
